import logging
log = logging.getLogger("statsdt")

# Default DataTable format
class BaseDTStats(object):
  def fill(self, records, tags, datefmt, x, y):
    return None, None, None
  
  def fmt2cols(self, cols, rows, colOrder):
    if 2 == len(colOrder):
      secondCol = cols.popitem()
      _cols = secondCol[1].popitem()
      cols = [secondCol[0], (_cols[0], _cols[1][0])]
      _rows = []
      for row in rows.iteritems():
        _rows.append([row[0], row[1].popitem()[1]])
      rows = _rows
    return cols, rows, colOrder

# X is date
class DTX(BaseDTStats):
  def fill(self, records, tags, datefmt, x, y):
    cols, rows, colOrder = {}, {}, []
    _cols = {} #non-first column
    firstCol = "Date"
    cols[(firstCol, "String", "")] = _cols
    dfmts = {} #temp data format row dict
    for rec in records:
      colName = " ".join(rec.tags) + "(" + rec.unit + ")"
      _cols[colName] = ("number", colName)
      tmpfmt = datefmt
      if 0 == len(datefmt):
        tmpfmt = str(rec.dfmt)
      rowName = self.getDateRowName(rows, dfmts, colName, rec.date, tmpfmt)
      if not rowName in rows:
        rows[rowName] = {}
      if colName in rows[rowName]:
        log.warn("V1[%s,%s,%.1f] and V2[%s,%s,%.1f] conflict!",
                 rowName, colName, rows[rowName][colName],
                 rec.date.strftime("%Y%m%d%H%M%S"), rec.tags, rec.value)
      rows[rowName][colName] = rec.value
    colOrder.append(firstCol)
    colOrder = colOrder+sorted(_cols.keys())
    return BaseDTStats.fmt2cols(self, cols, rows, colOrder)
  
  # If a date has same output with another under the date format,
  # the TWO date will all use the "%Y%m%d%H%M%S" format.
  def getDateRowName(self, rows, dfmts, colName, recdate, datefmt):
    rowName = recdate.strftime( datefmt )
    if "%Y%m%d%H%M%S" != datefmt:
      if not rowName in dfmts \
      or not rowName in rows \
      or not colName in rows[rowName]:
        dfmts[rowName] = recdate.strftime("%Y%m%d%H%M%S")
        return rowName
      assert(rowName in rows)
      rows[dfmts.pop(rowName)] = rows.pop(rowName)
      rowName = recdate.strftime("%Y%m%d%H%M%S")
    return rowName

# Y is date
class DTY(BaseDTStats):
  def fill(self, records, tags, datefmt, x, y):
    cols, rows, colOrder = {}, {}, []
    _cols = {} #non-first column
    firstCol = " ".join(tags)
    cols[(firstCol, "String", "")] = _cols
    for rec in records:
      colName = rec.date.strftime("%Y%m%d%H%M%S")
      tmpfmt = datefmt
      if 0 == len(datefmt):
        tmpfmt = str(rec.dfmt)
      _cols[colName] = ("number", rec.date.strftime(tmpfmt))
      rowName = " ".join(rec.tags) + "(" + rec.unit + ")"
      if not rowName in rows:
        rows[rowName] = {}
      if colName in rows[rowName]:
        log.warn("V1[%s,%s,%.1f] and V2[%s,%s,%.1f] conflict!",
                 rowName, colName, rows[rowName][colName],
                 rec.date.strftime("%Y%m%d%H%M%S"), rec.tags, rec.value)
      rows[rowName][colName] = rec.value
    colOrder.append(firstCol)
    colOrder = colOrder+sorted(_cols.keys())
    return BaseDTStats.fmt2cols(self, cols, rows, colOrder)
    
# X and Y are tags, and date is still in Y by default
#class TagsDT(BaseDTStats):
#  def fill(self, dtParams, records, tags, datefmt, x, y):
#    _cols = {} #non-first column
#    firstCol = " ".join(tags) # Whatever is ok.
#    cols[(firstCol, "String", "")] = _cols
#    for rec in records:
#      yTags = set(rec.tags) - set(tags) - set(y)
#      colName = " ".join(yTags) + rec.date.strftime("%Y%m%d%H%M%S")
#      _cols[colName] = ("number", colName)
#      rowName = " ".join(set(rec.tags) - set(tags) - set(x))
#      if not rowName in rows:
#        rows[rowName] = {}
#      rows[rowName][colName] = rec.value
#    colOrder.append(firstCol)
#    colOrder = colOrder+sorted(_cols.keys())
#    BaseDTStats.fill(self, dtParams, records, tags, datefmt, x, y)
#    

class DTTags(BaseDTStats):
  def fill(self, records, tags, datefmt, x, y):
    cols, rows, colOrder = {}, {}, []
    _cols = {} #non-first column
    firstCol = " ".join(tags) # Whatever is ok.
    cols[(firstCol, "String", "")] = _cols
    for rec in records:
      yTags = set(rec.tags) - (set(rec.tags) - set(y))
      if 0 == len("".join(yTags)):
        yTags = set(rec.tags) - set(x)
      colName = " ".join(yTags) + "(" + rec.date.strftime("%Y%m%d%H%M%S") + ")"
      tmpfmt = datefmt
      if 0 == len(datefmt):
        tmpfmt = str(rec.dfmt)
      _cols[colName] = ("number", " ".join(yTags) + "(" + rec.date.strftime(tmpfmt) + ")")
      
      rowName = " ".join(set(rec.tags) - (set(rec.tags) - set(x)))
      if 0 == len("".join(rowName)):
        rowName = " ".join(set(rec.tags) - set(y))
      if not rowName in rows:
        rows[rowName] = {}
      if colName in rows[rowName]:
        log.warn("V1[%s,%s,%.1f] and V2[%s,%s,%.1f] conflict!",
                 rowName, colName, rows[rowName][colName],
                 rec.date.strftime("%Y%m%d%H%M%S"), rec.tags, rec.value)
      rows[rowName][colName] = rec.value
    colOrder.append(firstCol)
    colOrder = colOrder+sorted(_cols.keys())
    return BaseDTStats.fmt2cols(self, cols, rows, colOrder)
    